home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.31-14 / scripts / pnmtologo.c < prev    next >
C/C++ Source or Header  |  2009-09-09  |  12KB  |  509 lines

  1.  
  2. /*
  3.  *  Convert a logo in ASCII PNM format to C source suitable for inclusion in
  4.  *  the Linux kernel
  5.  *
  6.  *  (C) Copyright 2001-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
  7.  *
  8.  *  --------------------------------------------------------------------------
  9.  *
  10.  *  This file is subject to the terms and conditions of the GNU General Public
  11.  *  License. See the file COPYING in the main directory of the Linux
  12.  *  distribution for more details.
  13.  */
  14.  
  15. #include <ctype.h>
  16. #include <errno.h>
  17. #include <stdarg.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <unistd.h>
  22.  
  23.  
  24. static const char *programname;
  25. static const char *filename;
  26. static const char *logoname = "linux_logo";
  27. static const char *outputname;
  28. static FILE *out;
  29.  
  30.  
  31. #define LINUX_LOGO_MONO        1    /* monochrome black/white */
  32. #define LINUX_LOGO_VGA16    2    /* 16 colors VGA text palette */
  33. #define LINUX_LOGO_CLUT224    3    /* 224 colors */
  34. #define LINUX_LOGO_GRAY256    4    /* 256 levels grayscale */
  35.  
  36. static const char *logo_types[LINUX_LOGO_GRAY256+1] = {
  37.     [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO",
  38.     [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16",
  39.     [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224",
  40.     [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256"
  41. };
  42.  
  43. #define MAX_LINUX_LOGO_COLORS    224
  44.  
  45. struct color {
  46.     unsigned char red;
  47.     unsigned char green;
  48.     unsigned char blue;
  49. };
  50.  
  51. static const struct color clut_vga16[16] = {
  52.     { 0x00, 0x00, 0x00 },
  53.     { 0x00, 0x00, 0xaa },
  54.     { 0x00, 0xaa, 0x00 },
  55.     { 0x00, 0xaa, 0xaa },
  56.     { 0xaa, 0x00, 0x00 },
  57.     { 0xaa, 0x00, 0xaa },
  58.     { 0xaa, 0x55, 0x00 },
  59.     { 0xaa, 0xaa, 0xaa },
  60.     { 0x55, 0x55, 0x55 },
  61.     { 0x55, 0x55, 0xff },
  62.     { 0x55, 0xff, 0x55 },
  63.     { 0x55, 0xff, 0xff },
  64.     { 0xff, 0x55, 0x55 },
  65.     { 0xff, 0x55, 0xff },
  66.     { 0xff, 0xff, 0x55 },
  67.     { 0xff, 0xff, 0xff },
  68. };
  69.  
  70.  
  71. static int logo_type = LINUX_LOGO_CLUT224;
  72. static unsigned int logo_width;
  73. static unsigned int logo_height;
  74. static struct color **logo_data;
  75. static struct color logo_clut[MAX_LINUX_LOGO_COLORS];
  76. static unsigned int logo_clutsize;
  77.  
  78. static void die(const char *fmt, ...)
  79.     __attribute__ ((noreturn)) __attribute ((format (printf, 1, 2)));
  80. static void usage(void) __attribute ((noreturn));
  81.  
  82.  
  83. static unsigned int get_number(FILE *fp)
  84. {
  85.     int c, val;
  86.  
  87.     /* Skip leading whitespace */
  88.     do {
  89.     c = fgetc(fp);
  90.     if (c == EOF)
  91.         die("%s: end of file\n", filename);
  92.     if (c == '#') {
  93.         /* Ignore comments 'till end of line */
  94.         do {
  95.         c = fgetc(fp);
  96.         if (c == EOF)
  97.             die("%s: end of file\n", filename);
  98.         } while (c != '\n');
  99.     }
  100.     } while (isspace(c));
  101.  
  102.     /* Parse decimal number */
  103.     val = 0;
  104.     while (isdigit(c)) {
  105.     val = 10*val+c-'0';
  106.     c = fgetc(fp);
  107.     if (c == EOF)
  108.         die("%s: end of file\n", filename);
  109.     }
  110.     return val;
  111. }
  112.  
  113. static unsigned int get_number255(FILE *fp, unsigned int maxval)
  114. {
  115.     unsigned int val = get_number(fp);
  116.     return (255*val+maxval/2)/maxval;
  117. }
  118.  
  119. static void read_image(void)
  120. {
  121.     FILE *fp;
  122.     unsigned int i, j;
  123.     int magic;
  124.     unsigned int maxval;
  125.  
  126.     /* open image file */
  127.     fp = fopen(filename, "r");
  128.     if (!fp)
  129.     die("Cannot open file %s: %s\n", filename, strerror(errno));
  130.  
  131.     /* check file type and read file header */
  132.     magic = fgetc(fp);
  133.     if (magic != 'P')
  134.     die("%s is not a PNM file\n", filename);
  135.     magic = fgetc(fp);
  136.     switch (magic) {
  137.     case '1':
  138.     case '2':
  139.     case '3':
  140.         /* Plain PBM/PGM/PPM */
  141.         break;
  142.  
  143.     case '4':
  144.     case '5':
  145.     case '6':
  146.         /* Binary PBM/PGM/PPM */
  147.         die("%s: Binary PNM is not supported\n"
  148.         "Use pnmnoraw(1) to convert it to ASCII PNM\n", filename);
  149.  
  150.     default:
  151.         die("%s is not a PNM file\n", filename);
  152.     }
  153.     logo_width = get_number(fp);
  154.     logo_height = get_number(fp);
  155.  
  156.     /* allocate image data */
  157.     logo_data = (struct color **)malloc(logo_height*sizeof(struct color *));
  158.     if (!logo_data)
  159.     die("%s\n", strerror(errno));
  160.     for (i = 0; i < logo_height; i++) {
  161.     logo_data[i] = malloc(logo_width*sizeof(struct color));
  162.     if (!logo_data[i])
  163.         die("%s\n", strerror(errno));
  164.     }
  165.  
  166.     /* read image data */
  167.     switch (magic) {
  168.     case '1':
  169.         /* Plain PBM */
  170.         for (i = 0; i < logo_height; i++)
  171.         for (j = 0; j < logo_width; j++)
  172.             logo_data[i][j].red = logo_data[i][j].green =
  173.             logo_data[i][j].blue = 255*(1-get_number(fp));
  174.         break;
  175.  
  176.     case '2':
  177.         /* Plain PGM */
  178.         maxval = get_number(fp);
  179.         for (i = 0; i < logo_height; i++)
  180.         for (j = 0; j < logo_width; j++)
  181.             logo_data[i][j].red = logo_data[i][j].green =
  182.             logo_data[i][j].blue = get_number255(fp, maxval);
  183.         break;
  184.  
  185.     case '3':
  186.         /* Plain PPM */
  187.         maxval = get_number(fp);
  188.         for (i = 0; i < logo_height; i++)
  189.         for (j = 0; j < logo_width; j++) {
  190.             logo_data[i][j].red = get_number255(fp, maxval);
  191.             logo_data[i][j].green = get_number255(fp, maxval);
  192.             logo_data[i][j].blue = get_number255(fp, maxval);
  193.         }
  194.         break;
  195.     }
  196.  
  197.     /* close file */
  198.     fclose(fp);
  199. }
  200.  
  201. static inline int is_black(struct color c)
  202. {
  203.     return c.red == 0 && c.green == 0 && c.blue == 0;
  204. }
  205.  
  206. static inline int is_white(struct color c)
  207. {
  208.     return c.red == 255 && c.green == 255 && c.blue == 255;
  209. }
  210.  
  211. static inline int is_gray(struct color c)
  212. {
  213.     return c.red == c.green && c.red == c.blue;
  214. }
  215.  
  216. static inline int is_equal(struct color c1, struct color c2)
  217. {
  218.     return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
  219. }
  220.  
  221. static void write_header(void)
  222. {
  223.     /* open logo file */
  224.     if (outputname) {
  225.     out = fopen(outputname, "w");
  226.     if (!out)
  227.         die("Cannot create file %s: %s\n", outputname, strerror(errno));
  228.     } else {
  229.     out = stdout;
  230.     }
  231.  
  232.     fputs("/*\n", out);
  233.     fputs(" *  DO NOT EDIT THIS FILE!\n", out);
  234.     fputs(" *\n", out);
  235.     fprintf(out, " *  It was automatically generated from %s\n", filename);
  236.     fputs(" *\n", out);
  237.     fprintf(out, " *  Linux logo %s\n", logoname);
  238.     fputs(" */\n\n", out);
  239.     fputs("#include <linux/linux_logo.h>\n\n", out);
  240.     fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
  241.         logoname);
  242. }
  243.  
  244. static void write_footer(void)
  245. {
  246.     fputs("\n};\n\n", out);
  247.     fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
  248.     fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
  249.     fprintf(out, "\t.width\t\t= %d,\n", logo_width);
  250.     fprintf(out, "\t.height\t\t= %d,\n", logo_height);
  251.     if (logo_type == LINUX_LOGO_CLUT224) {
  252.     fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize);
  253.     fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname);
  254.     }
  255.     fprintf(out, "\t.data\t\t= %s_data\n", logoname);
  256.     fputs("};\n\n", out);
  257.  
  258.     /* close logo file */
  259.     if (outputname)
  260.     fclose(out);
  261. }
  262.  
  263. static int write_hex_cnt;
  264.  
  265. static void write_hex(unsigned char byte)
  266. {
  267.     if (write_hex_cnt % 12)
  268.     fprintf(out, ", 0x%02x", byte);
  269.     else if (write_hex_cnt)
  270.     fprintf(out, ",\n\t0x%02x", byte);
  271.     else
  272.     fprintf(out, "\t0x%02x", byte);
  273.     write_hex_cnt++;
  274. }
  275.  
  276. static void write_logo_mono(void)
  277. {
  278.     unsigned int i, j;
  279.     unsigned char val, bit;
  280.  
  281.     /* validate image */
  282.     for (i = 0; i < logo_height; i++)
  283.     for (j = 0; j < logo_width; j++)
  284.         if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j]))
  285.         die("Image must be monochrome\n");
  286.  
  287.     /* write file header */
  288.     write_header();
  289.  
  290.     /* write logo data */
  291.     for (i = 0; i < logo_height; i++) {
  292.     for (j = 0; j < logo_width;) {
  293.         for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1)
  294.         if (logo_data[i][j].red)
  295.             val |= bit;
  296.         write_hex(val);
  297.     }
  298.     }
  299.  
  300.     /* write logo structure and file footer */
  301.     write_footer();
  302. }
  303.  
  304. static void write_logo_vga16(void)
  305. {
  306.     unsigned int i, j, k;
  307.     unsigned char val;
  308.  
  309.     /* validate image */
  310.     for (i = 0; i < logo_height; i++)
  311.     for (j = 0; j < logo_width; j++) {
  312.         for (k = 0; k < 16; k++)
  313.         if (is_equal(logo_data[i][j], clut_vga16[k]))
  314.             break;
  315.         if (k == 16)
  316.         die("Image must use the 16 console colors only\n"
  317.             "Use ppmquant(1) -map clut_vga16.ppm to reduce the number "
  318.             "of colors\n");
  319.     }
  320.  
  321.     /* write file header */
  322.     write_header();
  323.  
  324.     /* write logo data */
  325.     for (i = 0; i < logo_height; i++)
  326.     for (j = 0; j < logo_width; j++) {
  327.         for (k = 0; k < 16; k++)
  328.         if (is_equal(logo_data[i][j], clut_vga16[k]))
  329.             break;
  330.         val = k<<4;
  331.         if (++j < logo_width) {
  332.         for (k = 0; k < 16; k++)
  333.             if (is_equal(logo_data[i][j], clut_vga16[k]))
  334.             break;
  335.         val |= k;
  336.         }
  337.         write_hex(val);
  338.     }
  339.  
  340.     /* write logo structure and file footer */
  341.     write_footer();
  342. }
  343.  
  344. static void write_logo_clut224(void)
  345. {
  346.     unsigned int i, j, k;
  347.  
  348.     /* validate image */
  349.     for (i = 0; i < logo_height; i++)
  350.     for (j = 0; j < logo_width; j++) {
  351.         for (k = 0; k < logo_clutsize; k++)
  352.         if (is_equal(logo_data[i][j], logo_clut[k]))
  353.             break;
  354.         if (k == logo_clutsize) {
  355.         if (logo_clutsize == MAX_LINUX_LOGO_COLORS)
  356.             die("Image has more than %d colors\n"
  357.             "Use ppmquant(1) to reduce the number of colors\n",
  358.             MAX_LINUX_LOGO_COLORS);
  359.         logo_clut[logo_clutsize++] = logo_data[i][j];
  360.         }
  361.     }
  362.  
  363.     /* write file header */
  364.     write_header();
  365.  
  366.     /* write logo data */
  367.     for (i = 0; i < logo_height; i++)
  368.     for (j = 0; j < logo_width; j++) {
  369.         for (k = 0; k < logo_clutsize; k++)
  370.         if (is_equal(logo_data[i][j], logo_clut[k]))
  371.             break;
  372.         write_hex(k+32);
  373.     }
  374.     fputs("\n};\n\n", out);
  375.  
  376.     /* write logo clut */
  377.     fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
  378.         logoname);
  379.     write_hex_cnt = 0;
  380.     for (i = 0; i < logo_clutsize; i++) {
  381.     write_hex(logo_clut[i].red);
  382.     write_hex(logo_clut[i].green);
  383.     write_hex(logo_clut[i].blue);
  384.     }
  385.  
  386.     /* write logo structure and file footer */
  387.     write_footer();
  388. }
  389.  
  390. static void write_logo_gray256(void)
  391. {
  392.     unsigned int i, j;
  393.  
  394.     /* validate image */
  395.     for (i = 0; i < logo_height; i++)
  396.     for (j = 0; j < logo_width; j++)
  397.         if (!is_gray(logo_data[i][j]))
  398.         die("Image must be grayscale\n");
  399.  
  400.     /* write file header */
  401.     write_header();
  402.  
  403.     /* write logo data */
  404.     for (i = 0; i < logo_height; i++)
  405.     for (j = 0; j < logo_width; j++)
  406.         write_hex(logo_data[i][j].red);
  407.  
  408.     /* write logo structure and file footer */
  409.     write_footer();
  410. }
  411.  
  412. static void die(const char *fmt, ...)
  413. {
  414.     va_list ap;
  415.  
  416.     va_start(ap, fmt);
  417.     vfprintf(stderr, fmt, ap);
  418.     va_end(ap);
  419.  
  420.     exit(1);
  421. }
  422.  
  423. static void usage(void)
  424. {
  425.     die("\n"
  426.     "Usage: %s [options] <filename>\n"
  427.     "\n"
  428.     "Valid options:\n"
  429.     "    -h          : display this usage information\n"
  430.     "    -n <name>   : specify logo name (default: linux_logo)\n"
  431.     "    -o <output> : output to file <output> instead of stdout\n"
  432.     "    -t <type>   : specify logo type, one of\n"
  433.     "                      mono    : monochrome black/white\n"
  434.     "                      vga16   : 16 colors VGA text palette\n"
  435.     "                      clut224 : 224 colors (default)\n"
  436.     "                      gray256 : 256 levels grayscale\n"
  437.     "\n", programname);
  438. }
  439.  
  440. int main(int argc, char *argv[])
  441. {
  442.     int opt;
  443.  
  444.     programname = argv[0];
  445.  
  446.     opterr = 0;
  447.     while (1) {
  448.     opt = getopt(argc, argv, "hn:o:t:");
  449.     if (opt == -1)
  450.         break;
  451.  
  452.     switch (opt) {
  453.         case 'h':
  454.         usage();
  455.         break;
  456.  
  457.         case 'n':
  458.         logoname = optarg;
  459.         break;
  460.  
  461.         case 'o':
  462.         outputname = optarg;
  463.         break;
  464.  
  465.         case 't':
  466.         if (!strcmp(optarg, "mono"))
  467.             logo_type = LINUX_LOGO_MONO;
  468.         else if (!strcmp(optarg, "vga16"))
  469.             logo_type = LINUX_LOGO_VGA16;
  470.         else if (!strcmp(optarg, "clut224"))
  471.             logo_type = LINUX_LOGO_CLUT224;
  472.         else if (!strcmp(optarg, "gray256"))
  473.             logo_type = LINUX_LOGO_GRAY256;
  474.         else
  475.             usage();
  476.         break;
  477.  
  478.         default:
  479.         usage();
  480.         break;
  481.     }
  482.     }
  483.     if (optind != argc-1)
  484.     usage();
  485.  
  486.     filename = argv[optind];
  487.  
  488.     read_image();
  489.     switch (logo_type) {
  490.     case LINUX_LOGO_MONO:
  491.         write_logo_mono();
  492.         break;
  493.  
  494.     case LINUX_LOGO_VGA16:
  495.         write_logo_vga16();
  496.         break;
  497.  
  498.     case LINUX_LOGO_CLUT224:
  499.         write_logo_clut224();
  500.         break;
  501.  
  502.     case LINUX_LOGO_GRAY256:
  503.         write_logo_gray256();
  504.         break;
  505.     }
  506.     exit(0);
  507. }
  508.  
  509.